package com.lvandroid.play.player;

import android.view.SurfaceHolder;
import android.view.SurfaceView;

import androidx.annotation.NonNull;

import com.lvandroid.play.bean.VideoItem;
import com.lvandroid.play.util.LogUtil;

import java.io.IOException;
import java.util.List;

import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;

/**
 * 视频播放器，封装ijk-MediaPlayer
 */
public class VideoPlayer extends AllRoundPlayer<SurfaceView, VideoItem> {

    private static final String TAG = "VideoPlayer";

    private IjkMediaPlayer mPlayer;
    private InternalPrepareListener mInternalListener;

    VideoPlayer() {
        LogUtil.i(TAG, "VideoPlayer created.");
        configPlayer();
        initInternal();
    }

    /**
     * 初始化配置相关
     */
    private void configPlayer() {
        //默认不自动播放
        mAutoPlay = false;
    }

    /**
     * player相关初始化
     */
    private void initInternal() {
        mPlayer = new IjkMediaPlayer();
        mInternalListener = new InternalPrepareListener();
        mPlayItem = new VideoItem();
    }

    @Override
    public void setDisplay(SurfaceView sv) {
        LogUtil.i(TAG, "setDisplay ：" + sv);

        mDisplay = sv;
        mDisplay.getHolder().addCallback(new DisplayCallback());
        setDisplay(mDisplay.getHolder());
    }

    @Override
    public void setDisplay(SurfaceHolder sh) {
        LogUtil.i(TAG, "setDisplay ：" + sh);
        mState = PlayerState.STATE_INITIALED;
    }

    @Override
    public void playInternal() {
        LogUtil.i(TAG, "playInternal.");
    }

    @Override
    public void setDataSource(String source) {
        LogUtil.i(TAG, "setDataSource : " + source);
        try {
            mPlayItem.url = source;
            mPlayer.setDataSource(source);
            mState = PlayerState.STATE_INITIALED;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置player prepare监听，prepare完成之后才可以开始start。
     * @param l
     */
    public void setPrepareListener(OnPrepareListener l) {
        LogUtil.i(TAG, "setPrepareListener : " + l);
        mExternalListener = l;
        mPlayer.setOnPreparedListener(mInternalListener);
    }

    @Override
    public void setPlayItem(VideoItem item) {
        super.setPlayItem(item);
    }

    /**
     * player开始准备，为异步方式
     */
    @Override
    public void prepare() {
        LogUtil.i(TAG, "prepare.");
        if (mState != PlayerState.STATE_INITIALED) {
            throw new IllegalStateException("Player is UNINITIALIZED, please initial player before prepare!");
        }

        mPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);
        mPlayer.prepareAsync();
    }

    /**
     * 普通正常流程开始播放
     */
    @Override
    public void start() {
        LogUtil.i(TAG, "start.");
        if (mState != PlayerState.STATE_IDLE) {
            throw new IllegalStateException("Player is not prepared, please prepare player before start!");
        }

        if(!onViewPrepared) {
            LogUtil.w(TAG, "View is not ready!");
            return;
        }

        mPlayer.start();
        mState = PlayerState.STATE_START;
    }

    @Override
    public void start(String source) {
        LogUtil.i(TAG, "start : " + source);

        //这种播放模式的，默认自动播放
        mAutoPlay = true;
        mPlayItem.url = source;
        if(mState != PlayerState.STATE_INITIALED || null == mDisplay) {
            throw new IllegalStateException("Display uninitialized!");
        }

        setDataSource(source);
        if(mExternalListener == null) {
            setPrepareListener(null);
        }
        prepare();
    }

    @Override
    public void stop() {
        LogUtil.i(TAG, "stop.");
        if(mState != PlayerState.STATE_START) {
            throw new IllegalStateException("Player is not started, can not stop!");
        }

        mPlayer.stop();
        mState = PlayerState.STATE_STOP;
    }

    @Override
    public void pause() {
        LogUtil.i(TAG, "pause.");
        if(mState != PlayerState.STATE_START) {
            throw new IllegalStateException("Player is not started, can not pause!");
        }

        mPlayer.pause();
        mState = PlayerState.STATE_PAUSE;
    }

    @Override
    public void resume() {
        LogUtil.i(TAG, "resume.");
        if(mState != PlayerState.STATE_PAUSE) {
            throw new IllegalStateException("Player is not paused, can not resume!");
        }

        mState = PlayerState.STATE_START;
    }

    @Override
    public void reset() {
        LogUtil.i(TAG, "reset.");
        if(mState != PlayerState.STATE_STOP) {
            throw new IllegalStateException("Player is not stopped, can not reset!");
        }

        mPlayer.reset();
        mState = PlayerState.STATE_INITIALED;
    }

    @Override
    public void seek(long position) {
        LogUtil.i(TAG, "seek : " + position);
        if(mState != PlayerState.STATE_START || mState != PlayerState.STATE_PAUSE) {
            throw new IllegalStateException("Can not seek now!");
        }

        mPlayer.seekTo(position);
    }

    @Override
    public void loopPlay(boolean loop) {
        if(null != mPlayer) {
            mPlayer.setLooping(loop);
        }
    }

    /**
     * 更新PlayItem信息
     * @param iMediaPlayer
     */
    public void updatePlayItem(IMediaPlayer iMediaPlayer) {
        mPlayItem.url = iMediaPlayer.getDataSource();
        mPlayItem.mWidth = iMediaPlayer.getVideoWidth();
        mPlayItem.mHeight = iMediaPlayer.getVideoHeight();
        mPlayItem.mDuration = iMediaPlayer.getDuration();
        LogUtil.i(TAG, "updatePlayItem : " + mPlayItem);
    }

    boolean onViewPrepared = false;

    @Override
    public void start(List<String> source, SurfaceView display) {
        if(null == source || source.size() < 1) {
            throw new IllegalArgumentException("At least one source!");
        }

        setDisplay(display);
        //todo 暂不支持多个视频轮播
        start(source.get(0));
    }

    public void onViewPrepared(boolean prepared) {
        LogUtil.i(TAG, "onViewPrepared : " + prepared);
        onViewPrepared = prepared;
        mPlayer.setDisplay(mDisplay.getHolder());
        if(onViewPrepared) {
            if(mState == PlayerState.STATE_IDLE && mAutoPlay) {
                start();
            }
        } else {
            if(mState == PlayerState.STATE_START) {
                stop();
            }
        }
    }

    private class InternalPrepareListener implements IMediaPlayer.OnPreparedListener {

        @Override
        public void onPrepared(IMediaPlayer iMediaPlayer) {
            LogUtil.i(TAG, "internal onPrepared : " + iMediaPlayer);
            mState = PlayerState.STATE_IDLE;
            updatePlayItem(iMediaPlayer);
            if(null != mExternalListener) {
                mExternalListener.onPrepared(mPlayItem);
            }

            if(mAutoPlay) {
                start();
            }
        }
    }

    /**
     * 传入的surface view状态监听
     */
    private class DisplayCallback implements SurfaceHolder.Callback {

        @Override
        public void surfaceCreated(@NonNull SurfaceHolder holder) {
            LogUtil.i(TAG, "surfaceCreated");
            onViewPrepared(true);
        }

        @Override
        public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
            LogUtil.i(TAG, "surfaceChanged ： " + width + " x " + height);
        }

        @Override
        public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
            LogUtil.i(TAG, "surfaceDestroyed");
            onViewPrepared(false);
        }
    }

}
